package com.group9.handinhand.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.group9.handinhand.dao.CommunityDao;
import com.group9.handinhand.dao.UserDao;
import com.group9.handinhand.dao.model.Community;
import com.group9.handinhand.dao.model.CommunityMember;
import com.group9.handinhand.dao.model.CommunityPost;
import com.group9.handinhand.dao.model.Friendship;
import com.group9.handinhand.dao.model.FriendshipRequest;
import com.group9.handinhand.dao.model.MembershipRequest;
import com.group9.handinhand.dao.model.User;
import com.group9.handinhand.service.so.CommunityMemberSO;
import com.group9.handinhand.service.so.CommunityPostSO;
import com.group9.handinhand.service.so.CommunitySO;
import com.group9.handinhand.service.so.CommunityTagSO;
import com.group9.handinhand.service.so.FriendshipSO;
import com.group9.handinhand.service.so.MembershipRequestSO;
import com.group9.handinhand.service.so.UserSO;
import com.group9.handinhand.service.so.UserTagSO;
import com.group9.handinhand.utils.SemanticSearch;
/**
 * 
 *Class that defines the community service implementation.
 *
 */
@Transactional
@Service("communityService")
public class CommunityServiceImpl implements CommunityService {
	
	@Autowired
	CommunityDao communityDao;
	
	@Autowired
	UserDao userDao;
	
	@Autowired
	TagService tagService;

	@Override
	public CommunitySO getCommunityById(Long communityId) {
		Community community = communityDao.findCommunityById(communityId);
		if(community != null){
			return community.convertToServiceObject();
		}
		return null;
	}
	
	/**
	 * Saves the community service.
	 */
	@Override
	public CommunitySO saveCommunity(CommunitySO community, UserSO user) {
		community.getModerators().add(user);
		Community model = communityDao.saveCommunity(community.convertToModelObject());
		if(model != null) {
			CommunityMemberSO member = saveCommunityMember(model.convertToServiceObject(), user);
			if(member != null)
				return model.convertToServiceObject();
		}
		return null;
	}
	/**
	 * A get method.
	 * Gets the communities by user service object.
	 * @param user
	 * @ return list of the communities services
	 */
	@Override
	public List<CommunitySO> getCommunitiesByUser(UserSO user) {
		List<Community> modelList = communityDao.findCommunitiesByUser(user.convertToModelObject());
		List<CommunitySO> soList = new ArrayList<CommunitySO>();
		for (Community model : modelList) {
			soList.add(model.convertToServiceObject());
		}
		return soList;
	}
	
	/**
	 * a get method.
	 * Gets communities by user tag. 
	 * @param tag
	 * @return the list of the communities
	 */

	@Override
	public List<CommunitySO> getCommunitiesByTag(UserTagSO tag) {
		List<Community> modelList = communityDao.findCommunitiesByTag(tag);
		List<CommunitySO> soList = new ArrayList<CommunitySO>();
		for (Community model : modelList) {
			soList.add(model.convertToServiceObject());
		}
		return soList;
	}
	
	/**
	 * Gets the communities with specific tag keyword
	 *@param keyword
	 * @return list of the communities service object
	 */
	@Override
	public List<CommunitySO> getCommunitiesByTagKeyword(String keyword) {
		List<Community> modelList = communityDao.findCommunitiesByTagKeyword(keyword);
		List<CommunitySO> soList = new ArrayList<CommunitySO>();
		for (Community model : modelList) {
			soList.add(model.convertToServiceObject());
		}
		return soList;
	}
	/**
	 * Gets the communities with name
	 * @param keyword
	 * @return the list of communities
	 */
	@Override
	public List<CommunitySO> getCommunitiesByName(String keyword) {
		List<Community> modelList = communityDao.findCommunitiesByName(keyword);
		List<CommunitySO> soList = new ArrayList<CommunitySO>();
		for (Community model : modelList) {
			soList.add(model.convertToServiceObject());
		}
		return soList;
	}
	
	/**
	 * Saves the community members.
	 * @param community
	 * @param user
	 */
	@Override
	public CommunityMemberSO saveCommunityMember(CommunitySO community, UserSO user) {
		CommunityMemberSO so = new CommunityMemberSO();
		so.setUser(user);
		so.setCommunity(community);
		CommunityMember model = communityDao.saveCommunityMember(so.convertToModelObject());
		if(model != null)
			return model.convertToServiceObject();
		return null;
	}
	/**
	 * Saves membership request.
	 * @param community 
	 * @param user
	 * 
	 */
	@Override
	public MembershipRequestSO saveMembershipRequest(CommunitySO community, UserSO user) {
		MembershipRequestSO so = new MembershipRequestSO();
		so.setUser(user);
		so.setCommunity(community);
		MembershipRequest model = communityDao.saveMembershipRequest(so.convertToModelObject());
		if(model != null)
			return model.convertToServiceObject();
		return null;
	}
	/**
	 * Gets the community with community id and user id
	 * @param communityId
	 * @param userId
	 */
	@Override
	public CommunityMemberSO getCommunityMemberByCommunityIdAndUserId(Long communityId, Long userId){
		CommunityMember model = communityDao.findCommunityMemberByCommunityIdAndUserId(communityId, userId);
		if(model != null) {
			return model.convertToServiceObject();
		}
		return null;
	}
	/**
	 * Saves community post with community id and user id.
	 * @param communityId
	 * @param userId
	 * @param post
	 * 
	 */

	@Override
	public CommunityPostSO saveCommunityPost(Long communityId,Long userId, String post) {
		Community community = communityDao.findCommunityById(communityId);
		User user = userDao.findUserById(userId);
		CommunityPost communityPost = new CommunityPost();
		communityPost.setCommunity(community);
		communityPost.setContext(post);
		communityPost.setUser(user);
		
		CommunityPost model = communityDao.saveCommunityPost(communityPost);
		
		if(model != null) {
			return model.convertToServiceObject();
		}
		return null;
	}


	@Override
	public CommunitySO getModeratedCommunityByCommunityIdAndUserId(Long communityId, Long userId) {
		Community model = communityDao.findModeratedCommunityByCommunityIdAndUserId(communityId, userId);
		if(model != null) {
			return model.convertToServiceObject();
		}
		return null;
	}


	@Override
	public void updateCommunity(CommunitySO community) {
		communityDao.updateCommunity(community.convertToModelObject());
	}


	@Override
	public List<UserSO> getModeratorsByCommunityId(Long communityId) {
		List<User> modelList = communityDao.findModeratorsByCommunityId(communityId);
		List<UserSO> soList = new ArrayList<UserSO>();
		for (User model : modelList) {
			soList.add(model.convertToServiceObject());
		}
		return soList;
	}


	@Override
	public MembershipRequestSO getMembershipRequestByCommunityIdAndUserId(Long communityId, Long userId) {
		MembershipRequest model = communityDao.findMembershipRequestByCommunityIdAndUserId(communityId, userId);
		if(model != null) {
			return model.convertToServiceObject();
		}
		return null;
	}


	@Override
	public ArrayList<MembershipRequestSO> getMembershipRequests(Long communityId) {
		List<MembershipRequest> modelList = communityDao.findAllMembershipRequestsByCommunityId(communityId);
		ArrayList<MembershipRequestSO> soList = new ArrayList<MembershipRequestSO>();
		if(modelList != null) {
			for(MembershipRequest model:modelList){
				soList.add(model.convertToServiceObject());
			}
			return soList;
		}
		return null;

	}


	@Override
	public void deleteMembershipRequest(Long communityId, Long userId) {
		MembershipRequest model = communityDao.findMembershipRequestByCommunityIdAndUserId(communityId, userId);
		communityDao.deleteMembershipRequest(model);
	}


	@Override
	public ArrayList<CommunitySO> getCommunityRecommendations(CommunitySO community, UserSO user) {
		ArrayList<String> searchTags = new ArrayList<String>();
		for (CommunityTagSO ct : tagService.getCommunityTagsByCommunity(community)) {
			if(!ct.getTag().getTagName().equals(""))
			searchTags.add(ct.getTag().getTagName());
		}
		for (UserTagSO ut : tagService.getUserTagsByUser(user)) {
			if(!searchTags.contains(ut.getTag().getTagName()) && !ut.getTag().getTagName().equals(""))
				searchTags.add(ut.getTag().getTagName());
		}
		ArrayList<String> relatedTags = new SemanticSearch().doSemanticSearch(searchTags);
		return null;
	}
}
